/**
 * Copyright (C)  Gadglet .
 *
 * This file is part of Gadglet
 *
 * Gadglet is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Gadglet is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Gadglet. If not, see <http://www.gnu.org/licenses/>.
 */
package com.gadglet.core;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import com.gadglet.data.DomainUser;
import com.gadglet.data.Gadget;
import com.gadglet.data.UserProfile;
import com.gadglet.params.GadgetType;
import com.gadglet.params.GadgetViewState;
import com.gadglet.params.ProfPrivacyStatus;
import com.gadglet.params.ProfileFields;
import com.gadglet.params.ReqActionTypes;
import com.gadglet.params.ReqErrorTypes;
import com.gadglet.params.ReqParamNames;
import com.gadglet.params.SharedConstants;
import com.gadglet.params.SharingType;

/**
 * HttpServletRequestWrapper class that provides many services for Gadgets server 
 * side classes
 */
public class GadgletRequestWrapper extends HttpServletRequestWrapper {
	Logger log = Logger.getLogger(this.getClass().getName());

	public GadgletRequestWrapper(HttpServletRequest request) {
		super(request);
	}

	
	
	/**
	 * used in Bizlets registration process
	 * @return tokenId 
	 */
	public String getRegistrationTokenId() {
		return getParameter(SharedConstants.registrationTokenParamName);
	}

	
	/**
	 * @return UserProfile object saved in the session object
	 */
	public UserProfile getCurrentUserProfile() {
		if(getSession().getAttribute("userProfile")!=null)
			return (UserProfile) getSession().getAttribute("userProfile");
		
		return null;
	}
	


	/**
	 * @return profile nickname from the request
	 */
	public String getProfileNickName() {
		return getParameter(ProfileFields.PROFILE_NICKNAME.getParamName());
	}

	public String getCurrentUserProfileId() {
		if (getCurrentUserProfile() != null)
			return (getCurrentUserProfile().getProfileId());
		else
			return null;
	}
	
	
	
	/**
	 * @return userId. Works for both Minglets and Bizlets.
	 */
	public String getCurrentUserId(){
		
		if(getRequestedGadget()==null && getCurrentUserProfileId()!=null )
			return getCurrentUserProfileId(); 
		
		if(getRequestedGadget().getGadgletType().equals(GadgetType.MINGLET.getGadgetType()))
			return getCurrentUserProfileId();
		else
			return getCurrentDomainUserId();
	}

	
	/**
	 * @return the user selected Privacy Status
	 */
	public ProfPrivacyStatus getProfilePrivacy() {
		
		for(ProfPrivacyStatus pStatus : ProfPrivacyStatus.values())
			if (pStatus.getPrivacyStatus().equals(getParameter(ProfileFields.PROFILE_PRIVACY.getParamName())))
					return pStatus;
		
		// return PROTECTED if no match
		return ProfPrivacyStatus.PROTECTED;
		
	
	}

		
	/**
	 * @return the reqested gadget
	 */
	public Gadget getRequestedGadget() {
		return (Gadget) getAttribute(SharedConstants.gadgetRequstObject);
	}
	
	

		
	public void setRequestedGadget(Gadget gadget) {
		setAttribute(SharedConstants.gadgetRequstObject, gadget);
	}

	
	/**
	 * @return the Gadget client view during the request
	 */
	public GadgetViewState getGadgetViewState() {
		String viewType = getParameter(ReqParamNames.GADGET_VIEW_STATE
				.getParamName());

		if (viewType == null)
			return GadgetViewState.HOME;
		else if (viewType.equalsIgnoreCase(GadgetViewState.CANVAS.getviewType()))
			return GadgetViewState.CANVAS;
		else if (viewType.equalsIgnoreCase(GadgetViewState.PROFILE.getviewType()))
			return GadgetViewState.PROFILE;
		else if (viewType.equalsIgnoreCase(GadgetViewState.OTHER.getviewType()))
			return GadgetViewState.OTHER;
		else
			return GadgetViewState.HOME;
	}

	/**
	 * @return item key field name
	 */
	public String getItemKeyField() {
		return getParameter(ReqParamNames.ITEM_KEY_PARAM_NAME.getParamName());
	}

	
	public String getContentName(){
		
		return getParameter(ReqParamNames.CUSTOM_CONTENT_PARAM_NAME
				.getParamName());
		
	}
	
	
	/**
	 * @return request custom action
	 */
	public String getCustomAction() {
		return getParameter(ReqParamNames.CUSTOM_ACTION_PARAM_NAME
				.getParamName());
	}

	
	/**
	 * @return filter by parameter
	 */
	public String getFilterBy() {

		String filterBy = null;
		if (getParameter(ReqParamNames.FILTER_BY_PARAM_NAME.getParamName()) == null
				|| getParameter(
						ReqParamNames.FILTER_BY_PARAM_NAME.getParamName())
						.isEmpty())
			return filterBy;

		try {
			filterBy = URLDecoder.decode(
					getParameter(ReqParamNames.FILTER_BY_PARAM_NAME
							.getParamName()), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			log.warning(e1.getMessage());
		}

		return filterBy;

	}
	
	
	/**
	 * @return order  by parameter
	 */
	public String getOrderBy() {

		String orderBy = null;
		if (getParameter(ReqParamNames.SORT_BY_PARAM_NAME.getParamName()) == null
				|| getParameter(
						ReqParamNames.SORT_BY_PARAM_NAME.getParamName())
						.isEmpty())
			return orderBy;

		try {
			orderBy = URLDecoder.decode(
					getParameter(ReqParamNames.SORT_BY_PARAM_NAME
							.getParamName()), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			log.warning(e1.getMessage());
		}

		return orderBy;

	}

	
	
	/**
	 * @return Filter By Declaration 
	 */
	public String getFilterByDeclaration() {

		String filterBy = null;

		if (getParameter(ReqParamNames.FILTER_BY_FIELDS_PARAM_NAME
				.getParamName()) == null
				|| getParameter(
						ReqParamNames.FILTER_BY_FIELDS_PARAM_NAME
								.getParamName()).isEmpty())
			return filterBy;

		try {
			filterBy = URLDecoder.decode(
					getParameter(ReqParamNames.FILTER_BY_FIELDS_PARAM_NAME
							.getParamName()), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			log.warning(e1.getMessage());
		}

		return filterBy;
	}

	
	/**
	 * @return requested action
	 * @throws RequestException
	 */
	public ReqActionTypes getGadgetActionType() throws RequestException {
		
		for(ReqActionTypes aStatus : ReqActionTypes.values())
			if (aStatus.getActionType().equals(getParameter(ReqParamNames.ACTION_PARAM_NAME.getParamName())))
					return aStatus;
		throw new RequestException(ReqErrorTypes.UNRECOGNIZED_ACTION);

	}

	/**
	 * @return the item level sharing type requested by item owner
	 */
	public SharingType getSharingType(){

		if (getParameter(ReqParamNames.SHARE_TYPE.getParamName())==null)
			return null;
		if (getParameter(ReqParamNames.SHARE_TYPE.getParamName()).equals(SharingType.EDIT.getSharingType()))
			return SharingType.EDIT;
		else
			return SharingType.READ_ONLY;
	
	}
	
	
	/**
	 * @return Gadget name based on the url param "opensocial_app_url" or as define in the gadget
	 * @throws RequestException
	 */
	public String getGadgetName() throws RequestException {

		String gadgetName = null;
		String gadgetUrl = null;

		if (getParameter(ReqParamNames.APP_URL.getParamName()) != null) {
			try {
			
				gadgetUrl = URLDecoder.decode(
						getParameter(ReqParamNames.APP_URL.getParamName()),
						"UTF-8");
								

				int startPoint = gadgetUrl
						.indexOf(SharedConstants.gadgetDirName)
						+ SharedConstants.gadgetDirName.length();
						

				gadgetName = gadgetUrl.substring(startPoint,
						gadgetUrl.indexOf("/",startPoint));
							
				return gadgetName;

			}
			catch (Exception e) {
				log.warning(e.getMessage());

			}

		}

		gadgetName = getParameter(ReqParamNames.GADGET_PARAM_NAME
					.getParamName());
		
		if(gadgetName == null)
			throw new RequestException(ReqErrorTypes.UNRECOGNIZED_GADGET);
		
		return gadgetName;
	}

	
	
	/**
	 * @return content item key field
	 */
	public String getRequestItemKey() {
		return getParameter(ReqParamNames.ITEM_KEY_PARAM_NAME.getParamName());
	}
	
	/**
	 * @return OpenSocial ViewerId. works only for signed requests
	 */
	public String getOpenSocialViewerId() {

		return getParameter(getOpenSocialViewerIdParamName());
	}

	
	public String getOpenSocialViewerIdParamName() {

		return ReqParamNames.VIEWER_ID_KEY.getParamName();
	}

	public String getOpenSocialConsumerKey() {
		return getParameter(ReqParamNames.CONSUMER_KEY.getParamName());

	}

	public String getOpenSocialContainer() {

		return getParameter(getOpenSocialContainerParamName());
	}

	public String getOpenSocialContainerParamName() {

		return ReqParamNames.CONTAINER_KEY.getParamName();
	}

	public String getOpenSocialOwnerId() {

		return getParameter(ReqParamNames.OWNER_ID_KEY.getParamName());
	}

	public String getOpenSocialOwnerIdParamName() {

		return ReqParamNames.OWNER_ID_KEY.getParamName();
	}

	public long getStartFrom() {
		long startFrom = 0;

		try {
			if (getParameter(ReqParamNames.ITEMS_START_FROM.getParamName()) != null)
				startFrom = Integer
						.parseInt(getParameter(ReqParamNames.ITEMS_START_FROM
								.getParamName()));
		} catch (NumberFormatException e) {
			log.warning(e.getMessage());
		}

		return startFrom;
	}

	public long getItemNum() {
		long itemNum = 0;

		try {
			if (getParameter(ReqParamNames.ITEMS_NUM.getParamName()) != null)
				itemNum = Integer
						.parseInt(getParameter(ReqParamNames.ITEMS_NUM
								.getParamName()));
		} catch (NumberFormatException e) {
			log.warning(e.getMessage());
		}

		return itemNum;
	}

	
	
	/**
	 * Simple method to remove HTML from the content
	 * @param paramName request parameter name 
	 * @param logSecurity should log bad content
	 * @return
	 */
	public String getTrustedParameterValue(String paramName, boolean logSecurity) {
		String paramValue = null;
		String start = getParameter(paramName);
		paramValue = start;
		if (paramValue == null || paramValue.isEmpty())
			return paramValue;
		paramValue = paramValue.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
		paramValue = paramValue.replaceAll("eval\\((.*)\\)", "");
		paramValue = paramValue.replaceAll(
				"[\\\"\\\'][\\s]*((?i)javascript):(.*)[\\\"\\\']", "\"\"");
		paramValue = paramValue.replaceAll("((?i)script)", "");

		if (logSecurity && !start.equals(paramValue))
			log.warning("security alert:" + getOpenSocialViewerId() + "\n"
					+ start);

		return paramValue;
	}

	public DomainUser getCurrentDomainUser() {

		if(getSession().getAttribute("domainUser")!=null)
			return (DomainUser) getSession().getAttribute("domainUser");
		
		return null;
	}


	public String getCurrentDomainUserId() {
		if (getCurrentDomainUser() == null)
			return null;
		else
			return getCurrentDomainUser().getUniqueId();
	}

}
